<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head><meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"/>
<title>Mapl 结构</title><link href="../zdoc.css" rel="stylesheet" type="text/css"/><link href="../_rs/site.css" rel="stylesheet" type="text/css"/><script src="../_rs/jquery.js" language="Javascript"></script><script src="../_rs/site.js" language="Javascript"></script><script src="../_rs/z.js" language="Javascript"></script>
</head>
<body><a name="top"></a>
<div class="zdoc_header">Mapl 结构</div>
<div class="zdoc_author"><em>By:</em><b>juqkai</b><a href="mailto:juqkai@gmail.com">&lt;juqkai@gmail.com&gt;</a></div>
<div class="zdoc_body">
<ul class="zdoc_index_table">
<li>
<div><span class="num">1</span><a href="#为什么需要_Mapl_结构">为什么需要 Mapl 结构</a></div>
</li>
<li>
<div><span class="num">2</span><a href="#什么是_Mapl_结构?">什么是 Mapl 结构?</a></div>
</li>
<li>
<div><span class="num">3</span><a href="#Mapl转_对象">Mapl.转 对象</a></div>
</li>
<li>
<div><span class="num">4</span><a href="#对象转Maplist">对象转Maplist</a></div>
</li>
<li>
<div><span class="num">5</span><a href="#访问_Maplist">访问 Maplist</a></div>
</li>
<li>
<div><span class="num">6</span><a href="#maplist_合并">maplist 合并</a></div>
</li>
<li>
<div><span class="num">7</span><a href="#maplist_过滤">maplist 过滤</a></div>
</li>
<li>
<div><span class="num">8</span><a href="#maplist_结构转换">maplist 结构转换</a></div>
</li>
<li>
<div><span class="num">9</span><a href="#MapList的增删改">MapList的增删改</a></div>
</li>
</ul>
<div class="hr"><b></b></div>
<h1><a name="为什么需要_Mapl_结构"></a>为什么需要 Mapl 结构 </h1>
<div style="float:right;"><a href="#top">Top</a></div>
<p>一直以来都没有刻意的去思考说需要 Mapl 结构这样的东西. 所谓 Mapl 结构就是 Map-List 结构，我原来就叫 maplist 后来被灰太郎说太长，就改成 "mapl" 了</p>
<p>最初都是 wendal 在重写JSON的时候, 将JSON理解成了Mapl结构.然后突然在某一天发现, 咦, Mapl对象还可以这么用, 那么用, 慢慢的, 以Mapl 基础的小功能点越来越多, 已经不能够完全的与JSON概念协调, 所以才有了这样一个中间结构.</p>
<p>恩, 上面那段是给灰太狼, wendal看的. 我想你肯定看得头有点大, 要不我再说直白点, Mapl结构 就是为Json服务的, 为什么呢? MD, Json.fromJson()忒难用了, 要是只给它一个Reader, 而不给Type, 那它给我返回的就是 Mapl结构 , 苍天呀, 大地呀, 烦都烦死了. </p>
<p>我要取其中的某个值, 我得遍历N层的Map, List, 每次写这种东西的时候, 我都想哭, 所以干脆对它封装吧, 越封越多, 然后就有了这玩意...</p>
<p>当然, 它也与EL一样<span style="color:#0000AA;"><b> 满足一小撮人的一小撮要求</b></span></p>
<p>提醒: Mapl这个名词,是MapList的缩写</p>
<div class="hr"><b></b></div>
<h1><a name="什么是_Mapl_结构?"></a>什么是 Mapl 结构?</h1>
<div style="float:right;"><a href="#top">Top</a></div>
<p>一种以 Map, List 接口对象所组织起来的结构体系. 类似于JSON结构便于JAVA在内存中处理的结构. 主要提供键值对, 与列表的有机组合, 因这种结构只由Map, List组成, 因些称其为Mapl结构.</p>
<pre>Map a = new HashMap();
a.put("name","a");
Map b = new HashMap();
b.put("name","b");
Map c = new HashMap();
c.put("name","c");
List list = new ArrayList();
list.add(a);
list.add(b);
list.add(c);
Map d = new HashMap();
d.put("items", list);
</pre>
<p>通过上面的代码我们就组织了一个Mapl结构, 它等效于以下的JSON文档:</p>
<pre>{"items":[{"name":"a"},{"name":"b"},{"name":"c"}]}
</pre>
<p>当然, Mapl.仅可以用来表示JSON, 也可以用来表示JAVA对象的结构, 然后有了Mapl., 你会发现, 做转换, 合并, 都是非常轻松滴~~~ </p>
<p>具体规则:</p>
<ul type="disc">
<li>对象以Map存储, key为属性名, value为属性值</li>
<li>数组以List存储</li>
<li>Map直接存储为Map</li>
<li>List直接存储为List</li>
<li>只要不是List, Map存储的, 都认为是可以直接写入对象的</li>
</ul>
<div class="hr"><b></b></div>
<h1><a name="Mapl转_对象"></a>Mapl.转 对象</h1>
<div style="float:right;"><a href="#top">Top</a></div>
<p>也就是根据Mapl.及Type信息转换成一个Type的实体对象了啦, 直接看例子:</p>
<pre>class A{
    String name;
    Integer id;
}
class B{
    String name;
    List&lt;A&gt; as;
}
class C{
    public static void main(String args[]){
        String json = "{'name':'b', 'as':[{'name':'nutz','id':1},{'name':'jk','id':2}]}";
        //这样得到的就是Mapl结构的数据了.
        Object obj = Json.fromJson(json);
        
        B b = Mapl.maplistToObj(obj, B.class);
    }
}
</pre>
<p>通过上面的 Mapl.maplistToObj() 方法就可以将一个Mapl.象转换成B类型的实体对象. 我偷偷的告诉你哦, JSON里面也是这样搞的哦 ~~~先将JSON字符串转换成Mapl结构后再调用Mapl.maplistToObj()方法转换成对应的类型.</p>
<div class="hr"><b></b></div>
<h1><a name="对象转Maplist"></a>对象转Maplist</h1>
<div style="float:right;"><a href="#top">Top</a></div>
<p>除了通过JSON转换成Mapl结构以外, 还可以直接使用对象来转换成maplist结构</p>
<pre>A a = new A();
a.name="a"
B b = new B();
b.name = "b";
b.as = new ArrayList();
b.as.add(a);
Mapl.toMapl.b);
</pre>
<p>结果: </p>
<pre>{name:"b", as:[{name:"a", id:null}]}
</pre>
<p>通过toMapl.可以进行这种简单的转换</p>
<div class="hr"><b></b></div>
<h1><a name="访问_Maplist"></a>访问 Maplist</h1>
<div style="float:right;"><a href="#top">Top</a></div>
<p>就如我最开始说的那样, Json.fromJson 很难用, 就是因为在读取Mapl结构的数据时非常的繁杂, 经常需要很多层的类型转换.</p>
<pre>String json = "{'name':'b', 'as':[{'name':'nutz','id':1},{'name':'jk','id':2}]}";
//这样得到的就是Mapl结构的数据了.
Object obj = Json.fromJson(json);
</pre>
<p>上面的obj, 如果我想取as索引为1的name的值, 怎么办? 只能这样:</p>
<pre>Map map = (Map) obj;
List list = map.get("as");
Map item = list.get(1);
String name = item.get("name");
</pre>
<p>亲, 看到没, 看到没~~~妈哦, 还好这里只有几层, 要是再多几次这样的, 我一定会疯的, 你肯定也跟我一样吧. 所以咯, 让我们解脱吧~~~</p>
<pre>String name = (String) Mapl.cell(obj, "as[1].name");
</pre>
<p>完了? 这就样? 是的, 完了, 就这样, 一句话搞定. so easy~~~</p>
<p>最后说说关于里面path的规则:</p>
<ul type="disc">
<li>map的值访问直接使用 '.', 如: abc.name</li>
<li>list的访问使用 "名称[索引]", 如: as[1]. 当然要是不想写[]也可以使用 as.1.name的形式.</li>
<li>顶层为list时, 使用 "[索引].其它", 如: [1].name</li>
<li>如果想得到一个List, 而不是它某个值, 则可以使用 "名称" 不加 "[索引]". 如: as</li>
<li>如果List后加了"[]"中间却没有索引, 则默认访问第一个元素, 如: user[] 等效 user[1]</li>
</ul>
<div class="hr"><b></b></div>
<h1><a name="maplist_合并"></a>maplist 合并</h1>
<div style="float:right;"><a href="#top">Top</a></div>
<p>哇咔咔, 一个神器来鸟. 为嘛我要说它是神器呢, 看名字就知道了噻, 当然, 这个只是一小撮的一小撮的一小撮人会觉得是神器...额...好吧, 它只是一个没啥大用的一个伪神器...</p>
<p>顾名思义, maplist 合并, 就是将多个maplist合并在一起, 组成一个新的 maplist .</p>
<pre>String json1 = "{'name':'nutz'}";
String json2 = "{'age':12}"
Object obj1 = Json.fromJson(json1);
Object obj2 = Json.fromJson(json2);
Object obj3 = Mapl.merge(obj1, obj2);
</pre>
<p>最终obj3的输出将是: </p>
<pre>{"name":"nutz", 'age':12}
</pre>
<p>规则:</p>
<ul type="disc">
<li>普通对象, 保存为List, 但是要去除重复.</li>
<li>合并map, 如果key值相同, 那么后一个值覆盖前面的值, 注意, 对值将会进行递归合并</li>
<li>list不做递归合并, 只做简单的合并, 清除重复</li>
</ul>
<div class="hr"><b></b></div>
<h1><a name="maplist_过滤"></a>maplist 过滤</h1>
<div style="float:right;"><a href="#top">Top</a></div>
<p>这玩意有什么用呢, 用来剔除/筛选 maplist 中的值, 使maplist更加满足我们的需求. 还是用例子来说明吧.</p>
<pre>String json = "{name:'nutz', age:12, address:[{area:1,name:'abc'}, {area:2,name:'123'}]}";
Object obj = Json.fromJson(json);

List&lt;String&gt; list = new ArrayList&lt;String&gt;();
list.add("age");
list.add("address[].area");
Object newobj = Mapl.excludeFilter(obj, list);
</pre>
<p>结果: </p>
<pre>{name:'nutz', address:[{name:"abc"}, {name:"123"}]}
</pre>
<p>可以发现, 通过给定的过滤列表, 可以将原始的maplist结构给过滤掉满足条件的内容, 当然, 除了排除, 还有包含.</p>
<pre>String json = "{name:'nutz', age:12, address:[{area:1,name:'abc'}, {area:2,name:'123'}]}";
Object obj = Json.fromJson(json);

List&lt;String&gt; list = new ArrayList&lt;String&gt;();
list.add("age");
list.add("address[].area");
Object newobj = Mapl.includeFilter(obj, list);
</pre>
<p>结果: </p>
<pre>{age:12, address:[{area:1},{area:2}]}
</pre>
<p>excludeFilter与includeFilter是一组完全相反的功能.</p>
<p>path规则:</p>
<ul type="disc">
<li>map以 "key." 间隔</li>
<li>list以"key[]."间隔, 即多一个[], 注意其中没有索引哦.</li>
</ul>
<div class="hr"><b></b></div>
<h1><a name="maplist_结构转换"></a>maplist 结构转换</h1>
<div style="float:right;"><a href="#top">Top</a></div>
<p>好吧, 我觉得这个才是神器~~~啦~啦~~啦~~~啦~~~~完全是神一样的存在.</p>
<p>有没有使用过其它公司的API? 有吧, 其它公司都返回些什么格式? 它的格式与你程序的格式一样吗? 或许有, 但大部分是不一样的, 对吧. 既然这样, 那结构转换是肯定的了.</p>
<pre>String json = "[{'name':'jk', 'age':12},{'name':'nutz', 'age':5}]";
String model = "[{'name':['user[].姓名', 'people[].name'], 'age':['user[].年龄', 'people[].age']}]";
String dest = "{\"people\":[{\"age\":12,\"name\":\"jk\"}, "
              + "{\"age\":5,\"name\":\"nutz\"}],"
              + "\"user\":[{\"姓名\":\"jk\",\"年龄\":12}, "
              + "{\"姓名\":\"nutz\",\"年龄\":5}]}";
Object obj = Mapl.convert(Json.fromJson(new StringReader(json)), new StringReader(model));
assertEquals(dest, Json.toJson(obj, new JsonFormat()));
</pre>
<p>结果: </p>
<pre>{
    "people":[
        {"age":12,"name":"jk"}, 
        {"age":5,"name":"nutz"}
    ],
    "user":[
        {"姓名":"jk","年龄":12}, 
        {"姓名":"nutz","年龄":5}
    ]
}";
</pre>
<p>通过一个简单的操作, 我们就将一个maplist结构转换成了一个完全不一样的结构, 是不是很神奇?</p>
<p>什么是 maplist 结构转换呢? 就是将一种MapList结构转换成另外一种MapList结构.例: </p>
<pre>{
    "age":"123",
    "name":"juqkai"
}
</pre>
<p>转换成:</p>
<pre>{
    "年龄":"123",
    "姓名":"juqkai"
}
</pre>
<p>要进行这样的转换需要预先配置一个对应关系的配置, 具体的配置关系说明如下: </p>
<ul type="disc">
<li>使用原MapList一样的结构</li>
<li>有数组的, 只写第一个元素的结构</li>
<li>原结构中的值, 以字符串或字符串数组做为目标结构的对应关系</li>
<li>对应关系可以为数组</li>
<li>有数组的, 目标结构以key.abc来代替数组</li>
<li>原结构数组层次强制限定一致, 目标结构中'[]'的索引按原结构中出现先后顺序进行匹配.</li>
<li>如果原结果不存在, 那默认为0</li>
<li>未在模板中申明的不做转换</li>
</ul>
<p>例: </p>
<p>例1:</p>
<pre>  {
      "age":"user.年龄",
      "name":["user.name", "user.姓名"]
  }
</pre>
<p>例2</p>
<pre> (原json:[{"name":"nutz"},{"name":"juqkai"}]):
 [{
      "name":"[].姓名"
 }]
</pre>
<p>例3:</p>
<pre> {
      users:[
          {
              "name":["people[].name", "users[].name"],
              "age":"users[].name"
          }
      ]
 }
</pre>
<p></p>
<div class="hr"><b></b></div>
<h1><a name="MapList的增删改"></a>MapList的增删改</h1>
<div style="float:right;"><a href="#top">Top</a></div>
<p>只有访问, 肯定是不够的, 难免会添加, 删除, 修改某个结点. 所以, 特意的为您添加了这些功能.很简单的, 其实就三个接口而已.添加: Mapl.put, Mapl.del, Mapl.update. 具体的使用方法, 你看看注释咯, 简单得很. </p>
<p>除了上面的几个一次性的接口外. MapList还包含一个 MaplRebuild 类, 从名字就可以很容易知道它是干嘛的. 没错, 就是Maplist重建. 你可以根据已有的Maplist来构建它, 也可以全新的构建它, 然后你就可以对它进行添加新的结点, 修改某个结点, 或者删除某个结点. 如此反复.</p>
<p>下面看看Mapl.put的实现你就知道怎么用了:</p>
<pre>		/**
	     * 添加新的结点
	     * @param obj 原始的MapList
	     * @param path 路径
	     * @param val 值
	     */
	    public static void put(Object obj, String path, Object val) {
	        Object mapList = Mapl.toMaplist(val);
	        MaplRebuild rebuild = new MaplRebuild(obj);
	        rebuild.put(path, mapList);
	    }
</pre>
<div class="hr"><b></b></div>
</div>
<div class="zdoc_footer"><em>By:</em><b>juqkai</b><a href="mailto:juqkai@gmail.com">&lt;juqkai@gmail.com&gt;</a></div>
</body>
</html>